import logging

from flask import Blueprint, request, jsonify, make_response, redirect

from QiangZhi import JiaoWu
from QiangZhi import JiaoWu2

from utils.WXBizDataCrypt import WXBizDataCrypt
import requests
import random
import time
import hashlib
import json
import qrcode
import io

from user.model import Address
from user.model import User
from user.model import db
from order.model import Order
from order.model import Deliver
from order.model import Print
from activity.model import Activity
from activity.model import Checkin

import access
from database import R
from database import global_mode

user_blue = Blueprint('user', __name__)


def getUid():
    uid = R.get(request.headers.get('token'))
    if uid is None:
        return None
    else:
        return uid


@user_blue.before_request
def before_eq():
    if request.path == '/auth/wxlogin' or request.path == '/auth/gzhlogin' or request.path == '/auth/qrcode':
        pass
    elif getUid() is None:
        return {
                   'errmsg': 'token expired'
               }, 401


@user_blue.route('/auth/wxlogin')
def onlogin():
    code = request.args.get('code')
    userinfo = request.args.get('userinfo')
    userinfo = json.loads(userinfo)

    get_data = {
        'appid': 'wx518df2bfc44d1a33',
        'secret': '06281bb8b4f5fc0024f8fedb6674349a',
        'js_code': code,
        'grant_type': 'authorization_code'
    }
    res = requests.get('https://api.weixin.qq.com/sns/jscode2session', params=get_data)

    result = json.loads(res.text)
    if 'session_key' in result:
        # 找到键，返回自定义token
        r = random
        token = (str(r.randint(10000, 99999)) + str(time.time_ns())).encode('utf-8')
        token = hashlib.md5(token).hexdigest()

        # 先判断是否存在该用户
        user = User.query.filter(User.openid == result['openid']).first()
        if user is None:  # 不存在
            logging.info('user does not exist, create new.')
            user = User(openid=result['openid'], nickName=userinfo['nickName'], gender=userinfo['gender'],
                        avatarUrl=userinfo['avatarUrl'], money=0)
            db.session.add(user)
            db.session.commit()

            user2 = User.query.filter(User.openid == result['openid']).first()
            R.set(token, user2.id, ex=604800)
        else:
            user.gender = userinfo['gender']
            db.session.commit()
            R.set(token, user.id, ex=604800)
        return {
            'token': token
        }
    else:
        # 没找到，则返回errcode和错误提示
        return {
                   'errcode': result['errcode'],
                   'errmsg': result['errmsg']
               }, 201


@user_blue.route('/auth/gzhlogin')
def gzhlogin():
    code = request.args.get('code')
    get_data = {
        'appid': 'wx7d2fee7c9f9d6b75',
        'secret': 'b69085669731f3408f443f0caf568787',
        'code': code,
        'grant_type': 'authorization_code'
    }
    res = requests.get('https://api.weixin.qq.com/sns/oauth2/access_token', params=get_data)
    result = json.loads(res.text)

    if 'access_token' in result:
        token = access.getToken()
        res2 = requests.get('https://api.weixin.qq.com/cgi-bin/user/info?access_token=' + token + '&openid=' + result['openid'] + '&lang=zh_CN').json()
        if res2['subscribe'] == 0:
            return redirect('/static/fail.html')

        user = User.query.filter_by(id=int(request.args.get('state'))).first()
        if user is None:  # 不存在
            return '<h1 style="font-size: 32px">该用户未注册小程序</h1>', 200
        else:
            user.openid2 = result['openid']
            user.reminder = 1
            db.session.commit()
        return redirect('/static/success.html')


@user_blue.route('/auth/gzhqr', methods=['GET'])
def gzhqr():
    uid = getUid()
    return {
        'qrurl': 'https://yiyv.miniapp.client.everdo.cn/auth/qrcode?uid=' + str(uid)
    }, 200


@user_blue.route('/auth/qrcode', methods=['GET'])
def api_qrcode():
    uid = request.args.get('uid')
    url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx7d2fee7c9f9d6b75&redirect_uri=https%3a%2f' \
          '%2fyiyv.miniapp.client.everdo.cn%2fauth%2fgzhlogin&response_type=code&scope=snsapi_base&state=' + uid \
          +'#wechat_redirect'
    qr = qrcode.make(url)
    buffer = io.BytesIO()
    qr.save(buffer, "jpeg")
    buffer_str = buffer.getvalue()
    response = make_response(buffer_str)
    response.headers['Content-Type'] = 'image/jpeg'
    return response


@user_blue.route('/api/setting_jwxt', methods=['GET', 'POST'])
def bind_jw():
    if request.method == 'GET':
        # 如果用户已经绑定，则返回已经绑定的信息
        uid = getUid()
        user = User.query.filter(User.id == uid).first()
        if user.school is None:
            # 未绑定教务
            return {
                       'errmsg': '未绑定教务'
                   }, 201
        else:
            return {
                       'form': {
                           'school': user.school,
                           'snumber': user.xuehao,
                           'spass': user.jwpw
                       }
                   }, 200
    elif request.method == 'POST':
        # {
        #     school: '',
        #     snumber: '',
        #     spass: '',
        # }
        school = request.form.get('school')
        if school == 'scauzj':
            jw = JiaoWu.JiaoWu(request.form.get('snumber'), request.form.get('spass'), request.form.get('school'))
            jw.login_init()
            status = jw.login()
            if status == '验证码错误':
                return {
                           'errmsg': '验证码错误'
                       }, 201
            elif status == '账号或者密码错误':
                return {
                           'errmsg': '账号或密码错误'
                       }, 201
            elif status == '未知错误':
                return {
                           'errmsg': '未知错误'
                       }, 201

            # 绑定教务账户到用户
            # try:
            uid = getUid()
            user = User.query.filter(User.id == uid).first()
            user.school = request.form.get('school')
            user.xuehao = request.form.get('snumber')
            user.jwpw = request.form.get('spass')
            db.session.commit()

            jw.first_load(uid=uid)  # 第一次绑定，加载数据
            return {
                       'msg': '绑定成功'
                   }, 200
        elif school == 'ynnubs':
            jw = JiaoWu2.JiaoWu(request.form.get('snumber'), request.form.get('spass'), request.form.get('school'))
            jw.login_init()
            status = jw.login()
            if status == '验证码错误':
                return {
                           'errmsg': '验证码错误'
                       }, 201
            elif status == '账号或者密码错误':
                return {
                           'errmsg': '账号或密码错误'
                       }, 201
            elif status == '未知错误':
                return {
                           'errmsg': '未知错误'
                       }, 201

            # 绑定教务账户到用户
            # try:
            uid = getUid()
            user = User.query.filter(User.id == uid).first()
            user.school = request.form.get('school')
            user.xuehao = request.form.get('snumber')
            user.jwpw = request.form.get('spass')
            db.session.commit()

            jw.first_load(uid=uid)  # 第一次绑定，加载数据
            return {
                       'msg': '绑定成功'
                   }, 200
        # except Exception:
        #
        #     return {
        #                'errmsg': '拉取教务数据出错，请重试'
        #            }, 201


@user_blue.route('/api/setting_person', methods=['GET', 'POST'])
def setting_person():
    def getGender(gender):
        if gender == 1:
            return '男'
        elif gender == 0:
            return '女'
        else:
            return '女'

    def getGenderId(gender):
        if gender == '男':
            return 1
        elif gender == '女':
            return 0
        else:
            return 0

    if request.method == 'GET':
        # 需要判断用户是否已经绑定手机号，没有的话则需要前端先请求
        uid = getUid()
        user = User.query.filter(User.id == uid).first()
        if user.phone is None:
            return {
                       'errmsg': '用户未绑定手机号'
                   }, 201
        else:
            return {
                       'form': {
                           'name': user.realname,
                           'sex': getGender(user.gender),
                           'phone': user.phone
                       }
                   }, 200
    elif request.method == 'POST':
        uid = getUid()
        user = User.query.filter(User.id == uid).first()
        user.realname = request.form.get('name')
        # user.gender = getGenderId(request.form.get('sex'))
        user.phone = request.form.get('phone')
        db.session.commit()
        # 写入用户信息，绑定手机号
        return {
                   'msg': 'success'
               }, 200


@user_blue.route('/api/reminder', methods=['GET', 'POST'])
def set_reminder():
    def getMind(mind):
        if mind == 'true':
            return 1
        elif mind == 'false':
            return 0
        else:
            return 0

    if request.method == 'GET':
        # status = 获取状态
        uid = getUid()
        user = User.query.filter(User.id == uid).first()
        if user.reminder is None:
            return {
                       'setting_remind': False  # 如果没有数据，那就返回一个true
                   }, 200
        else:
            return {
                'setting_remind': user.reminder == 1  # 0 false / 1 true
            }
    elif request.method == 'POST':
        uid = getUid()
        user = User.query.filter(User.id == uid).first()
        if getMind(request.form.get('mind')) == 1:
            # 写入个人信息
            if user.openid2 is None:
                return {
                    'url': 'https://yiyv.miniapp.client.everdo.cn/auth/qrcode?uid=' + str(user.id)
                }, 201
            else:
                user.reminder = 1
                db.session.commit()
                return {
                    'msg': '开启成功'
                }, 200
        else:
            user.reminder = 0
        db.session.commit()
        return {
                   'msg': 'success'
               }, 200
    else:
        return {
                   'errmsg': '未知请求'
               }, 201


@user_blue.route('/api/setting_addr', methods=['GET', 'POST'])
def setting_addr():
    if request.method == 'GET':
        index = request.args.get('index', -1, type=int)
        if index >= 0:
            uid = getUid()
            user = User.query.filter(User.id == uid).first()
            address = Address.query.filter_by(userid=uid, addindex=index).first()  # 单个地址索引
            logging.info("querying %d" % address.id)
            if index > 2 or index < 0:
                return {
                           'errmsg': '地址序号超出索引范围'
                       }, 201
            else:
                return {
                           'form': {
                               'num': index,
                               'name': address.name,
                               'phone': address.phone,
                               'area': address.area,
                               'addr': address.addr
                           }
                       }, 200
        else:
            siteList = []
            uid = getUid()
            user = User.query.filter(User.id == uid).first()
            addresses = Address.query.filter_by(userid=uid).all()  # 多个地址索引

            for address in addresses:
                siteList.append({
                    'id': address.addindex,
                    'name': address.name,
                    'phone': address.phone,
                    'site': address.area + address.addr
                })

            return {
                       'siteList': siteList
                   }, 200
    elif request.method == 'POST':
        index = request.form.get('num')
        uid = getUid()
        exists = db.session.query(Address.id).filter_by(userid=uid, addindex=index).scalar() is not None
        if not exists:  # 没有这条记录
            logging.info('userid:%s address does not exist, create new' % uid)
            add = Address(userid=uid, name=request.form.get('name'), phone=request.form.get('phone'),
                          area=request.form.get('area'), addr=request.form.get('addr'),
                          addindex=request.form.get('num'))
            db.session.add(add)
            db.session.commit()
            return {
                       'msg': '新增地址成功'
                   }, 200
        else:
            logging.info('userid:%d address exists, modify it' % uid)
            address = Address.query.filter_by(userid=uid, addindex=index).first()
            address.name = request.form.get('name')
            address.phone = request.form.get('phone')
            address.area = request.form.get('area')
            address.addr = request.form.get('addr')
            address.addindex = request.form.get('num')
            db.session.commit()
            return {
                       'msg': '修改地址成功'
                   }, 200


# money接口用于查询用户余额和服务价格

@user_blue.route('/api/do_money', methods=['GET'])
def do_money():
    if request.method == 'GET':
        type = request.args.get('type')
        with open('user/money.json')as f:
            content = f.read()
            obj = json.loads(content)
        if type == 'user':
            # 从redis获取uid
            uid = getUid()
            # 从数据库查到用户
            user = User.query.filter(User.id == uid).first()
            money = user.money
            return {
                'money': money
            }, 200
        elif type == 'ddy':
            # 代打印价格
            money = obj['ddy']
            psmoney = obj['dyps']
            return {
                'money': money,
                'psmoney': psmoney
            }, 200
        elif type == 'qkd':
            dkd = obj['dkd']
            zkd = obj['zkd']
            xkd = obj['xkd']
            return {
                'ddk': dkd,
                'zdk': zkd,
                'xdk': xkd
            }, 200
        return {
                   'errmsg': 'type error(not found)'
               }, 201
    else:
        return {
            'errmsg': 'request type error, need GET(type)'
        }, 201


@user_blue.route('/auth/getphone', methods=['POST'])
def getphone():
    code = request.form.get('code')
    appId = 'wx518df2bfc44d1a33'
    encryptedData = request.form.get('encryptedData')
    iv = request.form.get('IV')

    get_data = {
        'appid': appId,
        'secret': '06281bb8b4f5fc0024f8fedb6674349a',
        'js_code': code,
        'grant_type': 'authorization_code'
    }
    res = requests.get('https://api.weixin.qq.com/sns/jscode2session', params=get_data)

    result = json.loads(res.text)
    if 'session_key' in result:
        sessionKey = result['session_key']
        # 解密初始化
        pc = WXBizDataCrypt(appId, sessionKey)
        # 解密
        data = pc.decrypt(encryptedData, iv)
        logging.info('phone decoded data: ' + str(data))
        return jsonify(data), 200
    else:
        return {
                   'errmsg': 'sessionkey获取失败'
               }, 200


@user_blue.route('/api/menum', methods=['GET'])
def menum():
    nums = [0, 0, 0, 0]
    uid = getUid()
    orders1 = Order.query.filter(Order.status.__lt__(1), Order.userid==uid).all()
    orders2 = Order.query.filter(Order.status == 1, Order.userid==uid).all()
    nums[0] = len(orders1)
    nums[1] = len(orders2)
    nums[2] = nums[0] + nums[1]
    return {
        'num': nums,
        'uid': uid
    }, 200


@user_blue.route('/api/actlist', methods=['GET'])
def actlist():
    uid = getUid()
    type = request.args.get('type')
    if type == 'all':
        acts = Activity.query.filter_by(status=0).order_by(Activity.id.desc()).all()
        act_list = []
        for act in acts:
            checkin = Checkin.query.filter_by(userid=uid, actid=act.id).first()
            people_count = Checkin.query.filter_by(actid=act.id).count()
            act_list.append({
                'id': act.id,
                'title': act.name,
                'subTitle': act.date1.strftime('%Y年%m月%d日') + ' ' + act.date2.strftime('%H:%M:%S'),
                'code': checkin.code if checkin is not None else '',
                'desc': act.descr,
                'img': act.img,
                'people': people_count,
                'join': checkin is not None
            })
        return {
            'cardlist': act_list
        }, 200
    elif type == 'me':
        checkins = Checkin.query.filter_by(userid=uid).all()
        act_list = []
        for checkin in checkins:
            act = Activity.query.filter_by(id=checkin.actid).first()
            people_count = Checkin.query.filter_by(actid=act.id).count()
            act_list.append({
                'id': act.id,
                'title': act.name,
                'subTitle': act.date1.strftime('%Y年%m月%d日') + ' ' + act.date2.strftime('%H:%M:%S'),
                'code': checkin.code if checkin is not None else '',
                'desc': act.descr,
                'img': act.img,
                'people': people_count,
                'join': checkin is not None
            })
        return {
            'cardlist': act_list
        }, 200


@user_blue.route('/api/actbyid', methods=['GET'])
def actbyid():
    uid = getUid()
    actid = request.args.get('id')
    act = Activity.query.filter_by(id=actid).first()
    checkin = Checkin.query.filter_by(userid=uid, actid=actid).first()
    return {
        'passage':{
            'joined': checkin is not None,
            'code': checkin.code if checkin is not None else '',
            'img': act.img,
            'time': act.date1.strftime('%Y年%m月%d日') + ' ' + act.date2.strftime('%H:%M:%S'),
            'name': act.name,
            'desc': act.descr,
            'timeline': [
                {
                    'desc': act.desc1,
                    'time': act.time1
                },
                {
                    'desc': act.desc2,
                    'time': act.time2
                },
                {
                    'desc': act.desc3,
                    'time': act.time3
                }
            ] if act.timeline == 1 else [],
            'pra_img': act.subimgurl if act.subimg == 1 else '',
            'rich_text': act.maindescdata if act.maindesc == 1 else ''
        }
    }, 200


@user_blue.route('/auth/actjoin', methods=['POST'])
def actjoin():
    uid = getUid()
    actid = request.form.get('id')
    type = request.form.get('type')
    r = random
    if type == 'add':
        checkin = Checkin(userid=uid, actid=actid, code=str(r.randint(100000, 999999)))
        db.session.add(checkin)
        db.session.commit()
        return {
            'msg': '报名成功'
        }, 200
    elif type == 'remove':
        checkin = Checkin.query.filter_by(userid=uid, actid=actid).first()
        db.session.delete(checkin)
        db.session.commit()
        return {
            'msg': '取消报名成功'
        }, 200


@user_blue.route('/api/getstation', methods=['GET'])
def getstation():
    with open('user/station.json', 'r', encoding='utf-8')as f:
        res = json.loads(f.read())
        f.close()
        return res, 200


@user_blue.route('/api/cancelorder', methods=['POST'])
def cancelorder():
    orderid = request.form.get('cancelid')
    user = User.query.filter_by(id=getUid()).first()
    order = Order.query.filter_by(id=orderid).first()
    if order.status == 0:
        if order.type == 'deliver':
            if global_mode == 1:
                money = order.money
                user.money += money

            deliver = Deliver.query.filter_by(orderid=orderid).first()
            db.session.delete(deliver)
            db.session.delete(order)
            db.session.commit()
            return {
                'msg': 'success'
            }, 200
        elif order.type == 'print':
            if global_mode == 1:
                money = order.money
                user.money += money

            p = Print.query.filter_by(orderid=orderid).first()
            db.session.delete(p)
            db.session.delete(order)
            db.session.commit()
            return {
                'msg': 'success'
            }, 200
    else:
        return {
            'errmsg': '订单不处于未接单状态'
        }, 201